library IEEE;
use work.all;
use work.prims.all;
use IEEE.numeric_bit.all;
use IEEE.numeric_std.all;

entity mem_controller is
	port (	CLK, RESET, START, STOP		:	in Bit;
			DELAY						:	in bit_vector(3 downto 0);
			READ, WRITE					:	out Bit;
			WADDR, RADDR				:	out bit_vector(3 downto 0));
end mem_controller;

architecture algorithmic of mem_controller is
begin
	process (CLK, RESET)
		variable STATE			:	bit_vector(1 downto 0);
		variable iWADDR, iRADDR	:	bit_vector(3 downto 0);
	begin
		if (CLK'event and CLK = '1') then
			case STATE is
				when "00" =>		--waiting for START
					if (START = '1') then
						iWADDR := "0000";
						iRADDR := DELAY;
						STATE := "01";
						WRITE <= '1';
					end if;
				when "01" =>		--dec RADDR, inc WADDR
					iWADDR := inc(iWADDR);
					iRADDR := dec(iRADDR);
					if (iRADDR = "0000") then
						STATE := "10";
						READ <= '1';
					end if;
				when "10" =>		--inc RADDR, inc WADDR
					iWADDR := inc(iWADDR);
					iRADDR := inc(iRADDR);
					if (STOP = '1') then
						WRITE <= '0';
						STATE := "11";
					end if;
				when "11" =>		--stopping, inc RADDR, no change in WADDR
					iRADDR := inc(iRADDR);
					if (iRADDR = iWADDR) then
						READ <= '0';
						STATE := "00";
					end if;
			end case;
		end if;
		if (RESET = '1') then
			STATE := "00";
		end if;
		WADDR <= iWADDR;
		RADDR <= iRADDR;
	end process;
end algorithmic;

use work.prims.all;

entity memory_unit is
	port (	CLK, READ, WRITE		:	in Bit;
			DATA_IN, RADDR, WADDR	:	in bit_vector(3 downto 0);
			DATA_OUT				:	out bit_vector(3 downto 0));
end memory_unit;

architecture algorithmic of memory_unit is
	type MEMORY is array(0 to 15) of bit_vector(3 downto 0);
begin
	process (CLK)
		variable MEM: MEMORY;
	begin
		if (WRITE = '1') then
			MEM(intval(WADDR)) := DATA_IN;
		end if;
		if (READ = '1') then
			if (WRITE = '0' OR WADDR /= RADDR) then
				DATA_OUT <= MEM(intval(RADDR));
			end if;
		end if;
	end process;
end algorithmic;

entity VDU is
	port (	CLK, RESET, START, STOP	:	in Bit;
			DELAY, DATA_IN			:	in bit_vector(3 downto 0);
			DATA_OUT				:	out bit_vector(3 downto 0));
end VDU;

